package org.web.webdisplay.server.biz.impl;


import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Service;
import org.web.base.domain.InsertGroup;
import org.web.base.domain.ResultDO;
import org.web.base.domain.UpdateGroup;
import org.web.base.domain.exception.ResultMessageEnum;
import org.web.base.domain.helper.ResultHelper;
import org.web.base.domain.helper.ServiceExceptionHelper;
import org.web.base.domain.helper.ValidationHelper;
import org.web.webdisplay.sdk.biz.VerifyIdentityBiz;
import org.web.webdisplay.sdk.dto.VerifyIdentityDTO;
import org.web.webdisplay.sdk.helper.VerifyIdentityHelper;
import org.web.webdisplay.server.domain.VerifyIdentityDO;
import org.web.webdisplay.server.domain.VerifyProtectRuleDO;
import org.web.webdisplay.server.domain.query.QueryVerifyIdentity;
import org.web.webdisplay.server.domain.query.QueryVerifyProtectRule;
import org.web.webdisplay.server.service.VerifyIdentityService;
import org.web.webdisplay.server.service.VerifyProtectRuleService;

import jakarta.annotation.Resource;
import java.util.Date;
import java.util.List;

public abstract class AbstractVerifyIdentityBizImpl implements VerifyIdentityBiz {

    @Resource
    private VerifyIdentityService verifyIdentityService;

    @Resource
    private VerifyProtectRuleService verifyProtectRuleService;


    @Override
    public ResultDO<VerifyIdentityDTO> generateVerifyIdentityCode(VerifyIdentityDTO verifyIdentityDTO) {
        ResultDO<VerifyIdentityDTO> resultDO = new ResultDO<>();
        try {
            resultDO.setDomain(verifyIdentityDTO);
            VerifyIdentityHelper.judgeGenerateVerifyIdentityCode(verifyIdentityDTO);

            QueryVerifyProtectRule queryVerifyProtectRule = new QueryVerifyProtectRule();
            queryVerifyProtectRule.setVerifyScenarios(verifyIdentityDTO.getVerifyScenarios());
            queryVerifyProtectRule.setRuleStatus("on");
            queryVerifyProtectRule.setLessThanCreateTime(new Date());

            List<VerifyProtectRuleDO> ruleList = verifyProtectRuleService.selectVerifyProtectRuleList(queryVerifyProtectRule);

            if (!ruleList.isEmpty()) {
                for (VerifyProtectRuleDO verifyProtectRuleDO : ruleList) {
                    QueryVerifyIdentity queryVerifyIdentity = getQueryVerifyIdentity(verifyIdentityDTO, verifyProtectRuleDO);
                    int count = verifyIdentityService.countVerifyIdentityList(queryVerifyIdentity);
                    short maxAttempts;
                    if (verifyProtectRuleDO.getMaxSendAttempts() != null) {
                        maxAttempts = verifyProtectRuleDO.getMaxSendAttempts();
                    } else {
                        maxAttempts = 1;
                    }
                    if (count >= maxAttempts) {
                        throw ServiceExceptionHelper.buildServiceException(ResultMessageEnum.DATA_OUT_OF_RANGE, "发送频率超出限制");
                    }
                }
            } else {
                // TODO 默认保护规则。
            }
            VerifyIdentityDO verifyIdentityDO = new VerifyIdentityDO();
            BeanUtils.copyProperties(verifyIdentityDTO, verifyIdentityDO);
            verifyIdentityService.insertVerifyIdentity(verifyIdentityDO);
        } catch (Exception e) {
            resultDO = ResultHelper.buildResultDOByException(e);
        }
        return resultDO;
    }

    private static QueryVerifyIdentity getQueryVerifyIdentity(VerifyIdentityDTO verifyIdentityDTO, VerifyProtectRuleDO verifyProtectRuleDO) {
        QueryVerifyIdentity queryVerifyIdentity = new QueryVerifyIdentity();
        queryVerifyIdentity.setVerifyScenarios(verifyIdentityDTO.getVerifyScenarios());
        queryVerifyIdentity.setSendMark(verifyIdentityDTO.getSendMark());
        queryVerifyIdentity.setLessThanCreateTime(new Date());
        if (verifyProtectRuleDO.getMonitoringIndicator().equals("SEND_MARK")) {
            queryVerifyIdentity.setSendMark(verifyIdentityDTO.getSendMark());
        } else if (verifyProtectRuleDO.getMonitoringIndicator().equals("USER_MARK")) {
            queryVerifyIdentity.setSendMark(verifyIdentityDTO.getUserMark());
        }
        int minutes_from_now = 1;
        if (verifyProtectRuleDO.getMinutesFromNow() != null) {
            minutes_from_now = verifyProtectRuleDO.getMinutesFromNow();
        }
        queryVerifyIdentity.setMoreThanCreateTime(new Date(new Date().getTime() - 1000L * 60 * minutes_from_now));
        return queryVerifyIdentity;
    }

    public abstract void generateVerifyCode(VerifyIdentityDTO verifyIdentityDTO);

    @Override
    public ResultDO<VerifyIdentityDTO> verifyIdentityCode(VerifyIdentityDTO verifyIdentityDTO) {
        ResultDO<VerifyIdentityDTO> resultDO = new ResultDO<>();
        try {
            resultDO.setDomain(verifyIdentityDTO);
            VerifyIdentityHelper.judgeVerifyIdentityCode(verifyIdentityDTO);

            QueryVerifyIdentity queryVerifyIdentity = new QueryVerifyIdentity();
            queryVerifyIdentity.setVerifyUuid(verifyIdentityDTO.getVerifyUuid());
            VerifyIdentityDO verifyIdentityDOFromDB = verifyIdentityService.selectOneVerifyIdentity(queryVerifyIdentity);
            if (verifyIdentityDOFromDB == null) {
                return ResultHelper.buildResultDOByResultMessageEnum(ResultMessageEnum.DATA_RECORD_NOT_EXIST, "验证信息不存在。");
            }

            String verifyStatus = verifyIdentityDOFromDB.getVerifyStatus();
            if ("CONFIRMED".equalsIgnoreCase(verifyStatus)) {
                return ResultHelper.buildResultDOByResultMessageEnum(ResultMessageEnum.DATA_OUT_OF_RANGE, "验证信息已确认。");
            } else if ("EXPIRED".equalsIgnoreCase(verifyStatus)) {
                return ResultHelper.buildResultDOByResultMessageEnum(ResultMessageEnum.DATA_OUT_OF_RANGE, "验证信息已过期。");
            } else if ("FAILED".equalsIgnoreCase(verifyStatus)) {
                return ResultHelper.buildResultDOByResultMessageEnum(ResultMessageEnum.DATA_OUT_OF_RANGE, "验证信息已失败。");
            }

            if (verifyIdentityDOFromDB.getExpiredEndDate().before(new Date())) {
                VerifyIdentityDO updateVerifyIdentityDO = new VerifyIdentityDO();
                updateVerifyIdentityDO.setVerifyIdentityId(verifyIdentityDOFromDB.getVerifyIdentityId());
                updateVerifyIdentityDO.setVerifyStatus("EXPIRED");
                updateVerifyIdentityDO.setVerifyComments("验证信息已过期。");

                verifyIdentityService.updateVerifyIdentityByVerifyIdentityId(updateVerifyIdentityDO);
                return ResultHelper.buildResultDOByResultMessageEnum(ResultMessageEnum.DATA_OUT_OF_RANGE, "验证信息已过期。");
            }

            Integer allowMaxCheckTimes = verifyIdentityDTO.getAllowMaxCheckTimes();

            String verifyMark = verifyIdentityDTO.getVerifyMark();
            String verifyMarkFromDB = verifyIdentityDOFromDB.getVerifyMark();
            if (verifyMark.equals(verifyMarkFromDB)) {
                VerifyIdentityDO updateVerifyIdentityDO = new VerifyIdentityDO();
                updateVerifyIdentityDO.setVerifyIdentityId(verifyIdentityDOFromDB.getVerifyIdentityId());
                updateVerifyIdentityDO.setVerifyStatus("CONFIRMED");
                updateVerifyIdentityDO.setVerifyComments("验证信息已确认。");
                verifyIdentityService.updateVerifyIdentityByVerifyIdentityId(updateVerifyIdentityDO);
                return resultDO;
            } else {
                VerifyIdentityDO updateVerifyIdentityDO = getVerifyIdentityDO(verifyIdentityDOFromDB, allowMaxCheckTimes);
                verifyIdentityService.updateVerifyIdentityByVerifyIdentityId(updateVerifyIdentityDO);
                return ResultHelper.buildResultDOByResultMessageEnum(ResultMessageEnum.PARAM_INVALID, "验证码不正确。");
            }
        } catch (Exception e) {
            resultDO = ResultHelper.buildResultDOByException(e);
        }
        return resultDO;
    }

    private static VerifyIdentityDO getVerifyIdentityDO(VerifyIdentityDO verifyIdentityDOFromDB, Integer allowMaxCheckTimes) {
        VerifyIdentityDO updateVerifyIdentityDO = new VerifyIdentityDO();
        updateVerifyIdentityDO.setVerifyIdentityId(verifyIdentityDOFromDB.getVerifyIdentityId());
        updateVerifyIdentityDO.setCheckTimes((short) (1+ verifyIdentityDOFromDB.getCheckTimes()));
        if(updateVerifyIdentityDO.getCheckTimes() >= allowMaxCheckTimes){
            updateVerifyIdentityDO.setVerifyStatus("FAILED");
            updateVerifyIdentityDO.setVerifyComments("验证失败，超出最大验证次数,"+ allowMaxCheckTimes +"次。");
        }
        return updateVerifyIdentityDO;
    }


}
